;; Spp is a programming language for parse programming language.

;; Basic type

    nil true 100 "str" :rule: (def (x) (first x))
    ("list") ["array"] {"hash-key" "hash-value"}

;; Spp support grammar, could gather rule:

    (grammar test)
    (my test  { ( <.ws> | <atom> )+ })
    (my ws    { \s+ })
    (my atom  { \w+ })
    (end test)

    (if ("abc cde" ~~ test)
       (say "it match words"))

;; Symbol and List:

    (my @a ('a 'b 'c))
    (if ('a in @a) (say "a is in list"))

;; Spp some like Lisp. It lend idea from Perl6, newlisp and many
;; programming language.

;; in Lisp or Scheme, local symbol is declare with (let ..) 
;; or (letn ..) with enclosed ( .. ), Spp could declare local symbol
;; with single line expression:

    (my sym 'abc)
    (undef sym)
    (if (not (defined sym))
      (say "sym have been deleted"))

;; We also could use operater in "infix" mode:

    (if (2 > 1) (say "a > 1"))

;; SPP support hex number and hex number char in rule

    (my @int 0xff)
    (my @char (char @int))
    (ok (@char ~~ { \xff }) @char)
    (ok (\n ~~ { \x0A }) \n)
    (ok (\f ~~ { \x0C }) \f)
    (ok (\a ~~ { \x07 }) \a)
    (ok (\e ~~ { \x1B }) \e)

;; \b is blank, it is space or \t, \B == [^\b]

    (ok (" " ~~ : \b :) " ")
    (ok (\t  ~~ : \b :) \t)

;; \l == [a-z] all lower alpha

    (ok (not-nil ("a" ~~ { \l })) true)
    (ok ("A" ~~ { \l }) nil)

;; \u == [A-Z] all upper alpha
 
    (ok ("a" ~~ {\u}) nil)
    (ok ("A" ~~ {\U}) nil)

;; \x == hex digit

    (if ("1234567890abcdef" ~~ {\x+})
      (say "\\x match hex digit"))

;; \d \w \s is same with PCRE

    (if ("\n\t\r " ~~ {\s+})
      (say "\\s match all space include newline"))

;; when parse grammar, have same daiyu to spp, we could compile
;; PCRE, then could use it to parse regex str, then transfer to
;; other str

    (if ("(?:abc)" ~~ Pcre) (say "Pcre is builtin grammar"))

;; Spp if use for parse other language, then need simulator other
;; language texing. hash array or other basic data type?

;; Spp need class package hash or ref?
;; package class hash use context
;; ref [context, def-name]
;; ref [str/list/array, method]

    (my @namespace (ns))
    (@namespace @key @value)
    (package @namespace) (end @namespace)
    (class @namespace) (end @namespace)

;; SPP support object call style:

   "str".len 
   [1,2,3].say

;; you could write code like smalltalk:

   [1,2,3] -> @x -> say
   grammar test -> my rule :\w: -> end test

;; if could tail the expression:

    (say "I can say" if nil)
    
;; push << and unshift >> is lend from Ruby:

    (begin (my x (0)) (x << 'a) (ok x (0 'a)))
    (begin (my x [0]) (x << 'a) (ok x [0, 'a]))
    (begin (my x (0)) ('a >> x) (ok x ('a 0)))
    (begin (my x [0]) ('a >> x) (ok x ['a, 0]))

;; split not only process str, but also array and list:

    (ok (split 'str) ('s 't 'r))
    (ok (split (1 2 3)) ((1) (2) (3)))
    (ok (split [1 2 3]) [[1] [2] [3]])

;; join could reverse split process

    (ok (join ('s 't 'r) 'str))
    (ok (join ((1) (2))) (1 2))
    (ok (join [[1] [2]]) [1 2])

;; first last, rest could process str/list/array

    (ok (first "str") "s")
    (ok (first (1 2 3)) 1)
    (ok (first [1 2 3]) 1)

    (ok (last "str") "r")
    (ok (last (1 2 3)) 3)
    (ok (last [1 2 3]) 3)
    
    (ok (rest "str") "tr")
    (ok (rest (1 2 3)) (2 3))
    (ok (rest [1 2 3]) [2 3])
    
;; nth could get index element of str/list/array

    (ok (nth 1 "012") "1")
    (ok (nth 1 (0 1 2)) 1)
    (ok (nth 1 [0 1 2]) 1)

;; slice could get piece of str/list/array

    (ok (slice "0123" 2) "23")
    (ok (slice (0 1 2 3) 2) (2 3))
    (ok (slice [0 1 2 3] 2) [2 3])
    
;; ssqq from China

(exit)

